/**
 * api_plugin.c - 使用钩子框架API的插件示例
 * 
 * 此插件演示如何使用钩子框架的API注册回调函数，
 * 而不是直接替换函数。
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "../../include/hook_framework.h"

/* 统计信息 */
static int g_open_count = 0;
static int g_read_count = 0;
static int g_write_count = 0;
static int g_socket_count = 0;

/* 监控线程 */
static pthread_t g_monitor_thread;
static int g_monitor_running = 0;

/**
 * open函数的前置回调
 */
static int open_pre_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    const char* pathname = (const char*)context->args[0];
    int flags = (int)(long)context->args[1];
    
    /* 增加计数 */
    g_open_count++;
    
    /* 记录信息 */
    log_message(LOG_INFO, "打开文件: %s, 标志: %d, 总计: %d", 
               pathname, flags, g_open_count);
    
    /* 允许操作继续 */
    return HOOK_CONTINUE;
}

/**
 * read函数的后置回调
 */
static int read_post_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    int fd = (int)(long)context->args[0];
    size_t count = (size_t)(long)context->args[2];
    ssize_t result = (ssize_t)(long)context->result;
    
    /* 只处理成功的读取 */
    if (result > 0) {
        g_read_count++;
        log_message(LOG_INFO, "读取文件描述符: %d, 请求: %zu字节, 实际: %zd字节, 总计: %d", 
                   fd, count, result, g_read_count);
    }
    
    return HOOK_CONTINUE;
}

/**
 * write函数的后置回调
 */
static int write_post_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    int fd = (int)(long)context->args[0];
    size_t count = (size_t)(long)context->args[2];
    ssize_t result = (ssize_t)(long)context->result;
    
    /* 只处理成功的写入 */
    if (result > 0) {
        g_write_count++;
        log_message(LOG_INFO, "写入文件描述符: %d, 请求: %zu字节, 实际: %zd字节, 总计: %d", 
                   fd, count, result, g_write_count);
    }
    
    return HOOK_CONTINUE;
}

/**
 * socket函数的前置回调
 */
static int socket_pre_callback(void* ctx, void* user_data) {
    hook_context_t* context = (hook_context_t*)ctx;
    int domain = (int)(long)context->args[0];
    int type = (int)(long)context->args[1];
    int protocol = (int)(long)context->args[2];
    
    /* 增加计数 */
    g_socket_count++;
    
    /* 记录信息 */
    log_message(LOG_INFO, "创建套接字: 域=%d, 类型=%d, 协议=%d, 总计: %d", 
               domain, type, protocol, g_socket_count);
    
    /* 允许操作继续 */
    return HOOK_CONTINUE;
}

/**
 * 监控线程函数
 */
static void* monitor_thread_func(void* arg) {
    log_message(LOG_INFO, "API插件监控线程已启动");
    
    while (g_monitor_running) {
        /* 每5秒输出一次统计信息 */
        sleep(5);
        
        if (g_monitor_running) {
            log_message(LOG_INFO, "=== 操作统计 ===");
            log_message(LOG_INFO, "文件打开: %d", g_open_count);
            log_message(LOG_INFO, "文件读取: %d", g_read_count);
            log_message(LOG_INFO, "文件写入: %d", g_write_count);
            log_message(LOG_INFO, "套接字创建: %d", g_socket_count);
            log_message(LOG_INFO, "================");
        }
    }
    
    log_message(LOG_INFO, "API插件监控线程已退出");
    return NULL;
}

/**
 * 加载插件
 */
int plugin_init(void) {
    log_message(LOG_INFO, "API插件正在初始化");
    
    /* 注册钩子点 */
    register_function_hook("open", HOOK_TYPE_LIBRARY, HOOK_GROUP_FILE_IO);
    register_function_hook("read", HOOK_TYPE_LIBRARY, HOOK_GROUP_FILE_IO);
    register_function_hook("write", HOOK_TYPE_LIBRARY, HOOK_GROUP_FILE_IO);
    register_function_hook("socket", HOOK_TYPE_LIBRARY, HOOK_GROUP_NETWORK);
    
    /* 注册回调 */
    register_pre_callback("open", open_pre_callback, NULL, 100);
    register_post_callback("read", read_post_callback, NULL, 100);
    register_post_callback("write", write_post_callback, NULL, 100);
    register_pre_callback("socket", socket_pre_callback, NULL, 100);
    
    /* 启动监控线程 */
    g_monitor_running = 1;
    if (pthread_create(&g_monitor_thread, NULL, monitor_thread_func, NULL) != 0) {
        log_message(LOG_ERROR, "无法创建监控线程");
        g_monitor_running = 0;
    }
    
    log_message(LOG_INFO, "API插件已初始化");
    return 0;
}

/**
 * 卸载插件
 */
void plugin_cleanup(void) {
    log_message(LOG_INFO, "API插件正在关闭");
    
    /* 停止监控线程 */
    if (g_monitor_running) {
        g_monitor_running = 0;
        pthread_join(g_monitor_thread, NULL);
    }
    
    /* 移除回调 */
    remove_pre_callback("open", open_pre_callback);
    remove_post_callback("read", read_post_callback);
    remove_post_callback("write", write_post_callback);
    remove_pre_callback("socket", socket_pre_callback);
    
    /* 输出最终统计信息 */
    log_message(LOG_INFO, "=== 最终统计 ===");
    log_message(LOG_INFO, "文件打开: %d", g_open_count);
    log_message(LOG_INFO, "文件读取: %d", g_read_count);
    log_message(LOG_INFO, "文件写入: %d", g_write_count);
    log_message(LOG_INFO, "套接字创建: %d", g_socket_count);
    log_message(LOG_INFO, "================");
    
    log_message(LOG_INFO, "API插件已关闭");
} 